// package: rewords-server-2024
// filename: admin
// author: diogoxiang@gmail.com
// time: 2024/11/12 17:58

package admin

import (
	"context"

	"rewords-server-2024/api/admin"
	"rewords-server-2024/internal/consts"
	"rewords-server-2024/internal/library/cache"
	"rewords-server-2024/internal/library/ecode"
	"rewords-server-2024/internal/logic/mgx"
	"rewords-server-2024/internal/model/entity"
	"rewords-server-2024/internal/model/input/form"
	"rewords-server-2024/internal/model/input/query_in"
	"rewords-server-2024/internal/service"
	"rewords-server-2024/utility/ufun"
	"rewords-server-2024/utility/ztime"

	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"go.mongodb.org/mongo-driver/bson"
)

var Amis = new(cAmis)

type cAmis struct{}

// QueryList 获取amis schema 列表
func (c *cAmis) QueryList(ctx context.Context, req *admin.AmisSchemaListReq) (res *admin.AmisSchemaListRes, err error) {

	fieldSelect := []string{
		"_id", "name", "path_name", "remark", "status", "created_at", "updated_at",
	}

	query, skip, limit, sortFields, projection := query_in.BuildMongoQueryWithPage(req.Conditions, req.OrderFields, req.Page, fieldSelect)
	g.Log().Debug(ctx, "MongoDB query conditions:", query)
	g.Log().Debug(ctx, "Skip:", skip, "Limit:", limit)

	result, err := service.Mgx().Find(ctx, consts.CAmisSchema, query, projection, skip, limit, sortFields)
	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}
	var lists []entity.SysAmisSchema

	if err = gconv.Struct(result, &lists); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}

	var total int64

	if req.Page.QueryCount {
		// 获取总记录数
		total, err = service.Mgx().CountDocuments(ctx, consts.CAmisSchema, query)
		if err != nil {
			return nil, gerror.Wrap(err, "获取总记录数失败")
		}
	}

	res = &admin.AmisSchemaListRes{
		Data: ufun.If(len(lists) > 0, lists, []entity.SysAmisSchema{}),
		PageResult: query_in.PageResult{
			Current:  (skip / limit) + 1,
			PageSize: limit,
			Total:    total,
			Pages:    (total + limit - 1) / limit,
			HasNext:  (skip + limit) < total,
		},
	}

	return res, nil
}

// QueryInfo 获取一个amis schema
func (c *cAmis) QueryInfo(ctx context.Context, req *admin.AmisSchemaInfoReq) (res *admin.AmisSchemaInfoRes, err error) {
	// 获取一些 特殊参数

	selectMap := bson.M{
		"_id": req.Id,
	}

	result, err := service.Mgx().FindOne(ctx, consts.CAmisSchema, selectMap, nil)

	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}
	schemaJSON := gjson.New(result["schema"])

	r := g.RequestFromCtx(ctx)
	// 将结果转换为JSON并直接返回
	r.Response.WriteJson(schemaJSON.Map())

	return
}

// AddSchema 添加一个amis schema 基本信息
func (c *cAmis) AddSchema(ctx context.Context, req *admin.AmisSchemaAddReq) (res *admin.AmisSchemaAddRes, err error) {
	Doc := &entity.SysAmisSchema{
		Name:     req.Name,
		PathName: req.PathName,
		Schema: string(gjson.MustEncode(g.Map{
			"type":  "page",
			"title": req.Name,
			"body":  []interface{}{},
		})),
		Status: "1",
		Remark: req.Remark,
	}
	eid, err := mgx.GetAutoInc(consts.CAmisSchema)
	if err != nil {
		// 处理错误，例如记录日志或返回错误信息
		g.Log().Printf(ctx, "Failed to get auto increment value for user: %v", err)
		// 根据实际情况决定如何处理错误，例如返回一个错误值或中断程序
		return nil, gerror.NewCode(ecode.InvalidParams)
	}
	Doc.Id = int64(eid)
	Doc.SetTimeValue(0)
	Doc.SetTimeValue(1)

	err = service.Mgx().InsertOne(ctx, consts.CAmisSchema, Doc)

	if err != nil {
		g.Log().Error(ctx, "Insert error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams, err.Error())
	}

	return &admin.AmisSchemaAddRes{
		Id: Doc.Id,
	}, nil
}

// UpdateSchemaMini 更新amis schema 名称、路径、备注、状态
func (c *cAmis) UpdateSchemaMini(ctx context.Context, req *admin.AmisSchemaMiniReq) (res *admin.AmisSchemaMiniRes, err error) {

	updateDoc := form.NewBuilder().
		Set("name", req.Name).
		SetIfNotEmpty("path_name", req.PathName).
		SetIfNotEmpty("remark", req.Remark).
		Set("status", req.Status).
		Set("updated_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CAmisSchema,
		bson.M{"_id": req.Id},
		bson.M{"$set": updateDoc},
	)
	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	return &admin.AmisSchemaMiniRes{
		Id: req.Id,
	}, nil
}

// UpdateSchema 添加一个amis schema , 只能更
// 只从 amisEditor 保存数据
func (c *cAmis) UpdateSchema(ctx context.Context, req *admin.AmisSchemaUpdateReq) (res *admin.AmisSchemaUpdateRes, err error) {

	//g.Log().Infof(ctx, "amis schema update id= %v", req.Id)
	r := g.RequestFromCtx(ctx)

	eid := r.GetQuery("id")
	reqbody := r.GetBodyString()

	//schemaJSON, _ := gjson.EncodeString(reqbody)

	updateDoc := form.NewBuilder().
		Set("schema", reqbody).
		Set("updated_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CAmisSchema,
		bson.M{"_id": eid.Int64()},
		bson.M{"$set": updateDoc},
	)
	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	selectMap := bson.M{
		"_id": eid.Int64(),
	}
	fieIdMap := bson.M{
		"_id":       1,
		"path_name": 1,
	}

	resDoc, err := service.Mgx().FindOne(ctx, consts.CAmisSchema, selectMap, fieIdMap)

	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}

	// 更新缓存
	cerr := cache.Instance("pages").Set(ctx, resDoc["path_name"], reqbody, 0)

	if cerr != nil {
		g.Log().Error(ctx, "Update cache error:", cerr)
	}

	return &admin.AmisSchemaUpdateRes{
		Id: eid.Int64(),
	}, nil
}

func (c *cAmis) DeleteSchema(ctx context.Context, req *admin.AmisSchemaDelReq) (res *admin.AmisSchemaDelRes, err error) {
	updateDoc := form.NewBuilder().
		Set("deleted_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CAmisSchema,
		bson.M{"_id": req.Id},
		bson.M{"$set": updateDoc},
	)

	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	return &admin.AmisSchemaDelRes{}, nil
}

func (c *cAmis) BatchUpdate(ctx context.Context, req *admin.AmisSchemaBatchUpdateReq) (res *admin.AmisSchemaBatchUpdateRes, err error) {
	updatedIds := make([]int64, 0)

	for _, item := range req.Rows {
		// 使用类型断言来获取 map 中的值
		id := gconv.Int64(item["id"])
		status, ok := item["status"].(string)
		if !ok {
			g.Log().Errorf(ctx, "Invalid status format in row: %v", item)
			continue
		}

		updateDoc := form.NewBuilder().
			SetIfNotEmpty("status", status).
			Set("updated_at", ztime.GetLocalTime()).
			Build()

		result, err := service.Mgx().UpdateOne(ctx,
			consts.CAmisSchema,
			bson.M{"_id": id},
			bson.M{"$set": updateDoc},
		)

		if err != nil {
			g.Log().Errorf(ctx, "Failed to update menu %d: %v", id, err)
			continue
		}

		if result.MatchedCount > 0 {
			updatedIds = append(updatedIds, id)
		}
	}

	return &admin.AmisSchemaBatchUpdateRes{
		Rows: updatedIds,
	}, err
}
